#include <linux/init.h>
#include <linux/module.h>
#include <asm-x86_64/bitops.h>

MODULE_LICENSE("Dual BSD/GPL");

void test_find_first_bit(void)
{
	unsigned long data[2];
	long ret = 0;

	printk(KERN_ERR "### find bit test ### \n");

	data[0] = 1;
	ret = find_first_bit(data, 8 * sizeof(__u64));
	printk(KERN_ERR "data:%lu first bit is %ld\n", data[0], ret);
	ret = find_next_bit(data, 8 * sizeof(__u64), 0);
	printk(KERN_ERR "data:%lu next bit is %ld\n", data[0], ret);

	data[0] = 0;
	ret = find_first_bit(data, 8 * sizeof(__u64));
	printk(KERN_ERR "data:%lu first bit is %ld\n", data[0], ret);
	ret = find_next_bit(data, 8 * sizeof(__u64), 1);
	printk(KERN_ERR "data:%lu next bit is %ld\n", data[0], ret);

	data[0] = 0;
	data[1] = 4;
	ret = find_first_bit(data, 8 * sizeof(__u64) * 2);
	printk(KERN_ERR "first bit is %ld\n", ret);
	ret = find_next_bit(data, 8 * sizeof(__u64) * 2, 1);
	printk(KERN_ERR "next bit is %ld\n",  ret);

	printk(KERN_ERR "### test init ###\n");
}

void test_set_bits(void)
{
	short data[3], little, big, mask;
	int start = 15, end = 32, sidx, soff, eidx, eoff, i;

	memset(data, 0, sizeof(short) * 3);

	sidx = start / (sizeof(short) * 8);
	soff = start % (sizeof(short) * 8);
	eidx = end / (sizeof(short) * 8);
	eoff = end % (sizeof(short) * 8);
	
	if (sidx == eidx) {
		little = (1 << soff) -1;
		big = (1 << (eoff + 1)) -1;
		mask = big & little;
		data[sidx] |= mask;
		goto print;
	}

	/* for the first short */
	little = ( 1 << soff ) -1;
	mask = ~little;
	data[sidx] |= mask;

	for (i = sidx + 1; i < eidx; i++) {
		data[i] = (short)-1;
	}

	mask = (1 << (eoff + 1)) -1;
	data[eidx] |= mask;

print:
	printk(KERN_ERR "data2:%d:data1:%d:data0:%d \n", data[2], data[1], data[0]);
}

static __init int test_init(void)
{
	printk(KERN_ERR "test init \n");

	test_find_first_bit();
//	test_set_bits();

	return 0;
}

static __exit void test_exit(void)
{
	printk(KERN_ERR "test exit \n");
}

module_init(test_init);
module_exit(test_exit);

